/*!
    \file    gd30ad3x40.c
    \brief   gd30ad3x40 driver
    
    \version 2024-10-08, V1.0.0, firmware for GD30AD3x40
*/

#include "gd30ad3x40.h"
#include "i2c_port.h"

uint16_t AD3x40_CONFIG;

/*!
    \brief      ALERT/RDY pin initialization
    \param[in]  none
    \param[in]  none
    \param[out] none
    \retval     none
*/ 
void ad3x40_gpio_init()
{
    rcu_periph_clock_enable(RCU_GPIOB);
    
    /* ADDR  PIN */
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
    gpio_bit_reset(GPIOB, GPIO_PIN_1);
    
    /* RDY PIN */
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
    /* enable and set key wakeup EXTI interrupt to the higher priority */
    nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
    
    /* connect key wakeup EXTI line to key GPIO pin */
    gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB, GPIO_PIN_SOURCE_0);
    /* configure key wakeup EXTI line */
    exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
    
    /* clear EXTI lines pending flag */
    exti_interrupt_flag_clear(EXTI_0);
}

/*!
    \brief      GD30AD3x40 write Register
    \param[in]  addr
                only one parameter can be selected which is shown as below:
      \arg      0x01: Config Register
      \arg      0x02: Lo_thresh Register
      \arg      0x03: Hi_thresh Register
    \param[in]  regs: the value need to be write to register
    \param[out] none
    \retval     none
*/
void ad3x40_write_regs(uint8_t addr, uint16_t regs)
{
    uint8_t reg_val;
    uint8_t reg_addr = addr;

    ad3x40_i2c_tx_start();

    ad3x40_i2c_tx_byte(reg_addr);

    reg_val = regs>>8;
    ad3x40_i2c_tx_byte(reg_val);
      
    reg_val = regs&0xFF;
    ad3x40_i2c_tx_byte(reg_val);
      
    ad3x40_i2c_tx_stop();
}

/*!
    \brief      GD30AD3x40 read Register by 16 bit
    \param[in]  addr
                only one parameter can be selected which is shown as below:
      \arg      0x00: Conversion Register
      \arg      0x01: Config Register
    \param[out] none
    \retval     the read value of register
*/
uint16_t ad3x40_read_regs16(uint8_t addr)
{
    uint8_t reg_val;
    uint8_t reg_addr = addr;
    uint16_t reg_rtu = 0;

     
    ad3x40_i2c_tx_start();
    ad3x40_i2c_tx_byte(reg_addr);
    ad3x40_i2c_tx_stop(); 

    ad3x40_i2c_rx_start();
    reg_val = ad3x40_i2c_rx_byte();

    reg_rtu |= reg_val<<8;

    reg_val = ad3x40_i2c_rx_byte();

    reg_rtu |= reg_val;

    ad3x40_i2c_rx_stop();

    return reg_rtu;
}

/*!
    \brief      GD30AD3x40 read Register by 32 bit
    \param[in]  addr
                only one parameter can be selected which is shown as below:
      \arg      0x00: Conversion Register
      \arg      0x01: Config Register
    \param[out] none
    \retval     the read value of register
*/
uint32_t ad3x40_read_regs32(uint8_t addr)
{
    uint8_t reg_val;
    uint8_t reg_addr = addr;
    uint32_t reg_rtu = 0;

    ad3x40_i2c_tx_start();
    ad3x40_i2c_tx_byte(reg_addr);
    ad3x40_i2c_tx_stop(); 

    ad3x40_i2c_rx_start();
    
    reg_val = ad3x40_i2c_rx_byte_ack();
    reg_rtu |= reg_val<<16;
    
    reg_val = ad3x40_i2c_rx_byte();
    reg_rtu |= reg_val<<8;

    reg_val = ad3x40_i2c_rx_byte();
    reg_rtu |= reg_val;

    ad3x40_i2c_rx_stop();

    return (reg_rtu);
}

/*!
    \brief      GD30AD3340 read Register
    \param[in]  none
    \param[out] none
    \retval     the result of the conversion
*/
uint16_t ad3340_read_data()
{
    uint16_t data = ad3x40_read_regs16(AD3340_CONVERSION_ADDRESS);
    
    return data;
}

/*!
    \brief      GD30AD3640 read Register
    \param[in]  none
    \param[out] none
    \retval     the result of the conversion
*/
uint32_t ad3640_read_data()
{
    uint32_t data = ad3x40_read_regs32(AD3640_CONVERSION_ADDRESS);
    
    return data;
}

/*!
    \brief      GD30AD3x40 stop conversion
    \param[in]  none
    \param[out] none
    \retval     the result of the conversion
*/
void ad3x40_stop_conver()
{
    AD3x40_CONFIG |= AD3x40_REG_CONFIG_MODE_SINGLE;
    ad3x40_write_regs(AD3x40_CONFIG_ADDRESS, AD3x40_CONFIG);
}

/*!
    \brief      GD30AD3x40 reset
    \param[in]  none
    \param[out] none
    \retval     the result of the conversion
*/
void ad3x40_reset()
{
    ad3x40_write_regs(AD3x40_CONFIG_ADDRESS, AD3x40_CONFIG_DEFAULT);
    ad3x40_write_regs(AD3x40_LO_THRESH_ADDRESS, AD3x40_LO_THRESH_DEFAULT);
    ad3x40_write_regs(AD3x40_HI_THRESH_ADDRESS, AD3x40_HI_THRESH_DEFAULT);
}
